/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: Frank
 * 系统版本: 1.0.0
 * 开发人员: Frank
 * 开发时间: 2019/12/12 10:29
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.spring.arch.uaa.web.controller;

import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.Lists;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.common.utils.HttpUtils;
import com.spring.arch.uaa.bean.EmployeeBean;
import com.spring.arch.uaa.dto.EmployeeDTO;
import com.spring.arch.uaa.enums.Constant;
import com.spring.arch.uaa.errorcode.UaaErrorCode;
import com.spring.arch.uaa.web.converter.EmployeeConverter;
import com.spring.arch.uaa.web.converter.WebTenantEmployeeConverter;
import com.spring.arch.uaa.web.dto.WebTenantEmployeeDTO;
import com.spring.arch.common.dto.result.ResultDTO;
import com.spring.arch.common.exception.ExceptionHolder;
import com.spring.arch.common.utils.HttpUtils;
import com.spring.arch.uaa.bean.EmployeeBean;
import com.spring.arch.uaa.dto.EmployeeDTO;
import com.spring.arch.uaa.enums.Constant;
import com.spring.arch.uaa.errorcode.UaaErrorCode;
import com.spring.arch.uaa.model.*;
import com.spring.arch.uaa.repository.*;
import com.spring.arch.uaa.service.EmployeeService;
import com.spring.arch.uaa.web.converter.EmployeeConverter;
import com.spring.arch.uaa.web.converter.WebTenantEmployeeConverter;
import com.spring.arch.uaa.web.dto.WebTenantEmployeeDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.UUID;

import static com.spring.arch.uaa.enums.Constant.PROJECT_ADMIN_ROLE_CODE;
import static com.spring.arch.uaa.enums.Constant.TENANT_ADMIN_ROLE_CODE;
import static com.spring.arch.uaa.errorcode.UaaErrorCode.*;

/**
 * 人员管理Api
 *
 * @author Frank
 * @version 1.0.0.1
 * @since 2019/12/12 10:29
 */
@Slf4j
@RestController
@RequestMapping(value = "uaa/w/employees", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = {"租户人员管理Api"}, produces = MediaType.APPLICATION_JSON_VALUE, protocols = "http, https")
public class EmployeeController {

    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private EmployeeConverter employeeConverter;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private TenantRepository tenantRepository;
    @Autowired
    private ProjectRepository projectRepository;
    @Autowired
    private TenantEmployeeRepository tenantEmployeeRepository;
    @Autowired
    private WebTenantEmployeeConverter tenantEmployeeConverter;
    @Autowired
    private OrganizationEmployeeRepository organizationEmployeeRepository;
    @Autowired
    private OrganizationEmployeeRoleRepository organizationEmployeeRoleRepository;
    @Autowired
    private UserRepository userRepository;

    /**
     * 创建操作
     * @param employeeDTO 创建资源的DTO
     * @return 创建资源的DTO
     */
    @Timed
    @ApiOperation(value = "创建操作")
    @PostMapping
    public ResultDTO<Void> create(@Valid @RequestBody final EmployeeDTO employeeDTO, HttpServletRequest request) {
        String clientIP = HttpUtils.getClientIP(request);
        final EmployeeBean bean = employeeConverter.toBean(employeeDTO);
        TenantEmployee tenantEmployee = employeeService.save(bean);
        if (log.isInfoEnabled()) {
            log.info("[{}] employee instance {} was created.", clientIP, tenantEmployee.getName(), tenantEmployee.getId());
        }
        return ResultDTO.success();
    }

    /**
     * 更新操作
     * @param employeeDTO 更新资源的DTO
     * @return 创建资源的DTO
     */
    @Timed
    @ApiOperation(value = "更新操作")
    @PutMapping(value = "/{id}")
    public ResultDTO<Void> update(@PathVariable UUID id, @Valid @RequestBody final EmployeeDTO employeeDTO, HttpServletRequest request) {
        String clientIP = HttpUtils.getClientIP(request);
        employeeDTO.setId(id);
        final EmployeeBean bean = employeeConverter.toBean(employeeDTO);
        TenantEmployee tenantEmployee = employeeService.save(bean);
        if (log.isInfoEnabled()) {
            log.info("[{}] employee instance {} was update.", clientIP, tenantEmployee.getName(), tenantEmployee.getId());
        }
        return ResultDTO.success();
    }

    /**
     * 创建租户管理员
     * @param employeeDTO 创建资源的DTO
     * @return 创建资源的DTO
     */
    @Timed
    @ApiOperation(value = "创建租户管理员")
    @PostMapping(value = "/tenantAdmin")
    public ResultDTO<Void> createTenantAdmin(@Valid @RequestBody final EmployeeDTO employeeDTO, HttpServletRequest request) {
        String clientIP = HttpUtils.getClientIP(request);
        // 获取租户信息
        @NotNull UUID tenantId = employeeDTO.getTenantId();
        Tenant tenant = tenantRepository.findById(tenantId)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001001001, String.valueOf(tenantId)));
        Organization rootOrganization = tenant.getRootOrganization();
        if (rootOrganization == null) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001001006);
        }
        // 创建管理员编码
        employeeDTO.setCode(Constant.tenantAdminCode(tenant.getCode()));
        final EmployeeBean bean = employeeConverter.toBean(employeeDTO);
        bean.setOrganization(rootOrganization);
        // 设置租户管理员角色
        Role tenantAdminRole = roleRepository.findByCode(Constant.TENANT_ADMIN_ROLE_CODE)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001006001, Constant.TENANT_ADMIN_ROLE_CODE));
        bean.setRoles(Lists.newArrayList(tenantAdminRole));
        TenantEmployee tenantEmployee = employeeService.save(bean);
        if (log.isInfoEnabled()) {
            log.info("[{}] tenant admin instance {} was created.", clientIP, tenantEmployee.getName(), tenantEmployee.getId());
        }
        return ResultDTO.success();
    }

    /**
     * 创建项目管理员
     * @param employeeDTO 创建资源的DTO
     * @return 创建资源的DTO
     */
    @Timed
    @ApiOperation(value = "创建项目管理员")
    @PostMapping(value = "/projectAdmin")
    public ResultDTO<Void> createProjectAdmin(@Valid @RequestBody final EmployeeDTO employeeDTO, HttpServletRequest request) {
        String clientIP = HttpUtils.getClientIP(request);
        // 获取项目信息
        UUID projectId = employeeDTO.getProjectId();
        if  (projectId == null) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001002002);
        }
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001002001, String.valueOf(projectId)));
        Organization rootOrganization = project.getRootOrganization();
        if (rootOrganization == null) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001002003);
        }
        // 创建管理员编码
        employeeDTO.setCode(Constant.projectAdminCode(project.getCode()));
        final EmployeeBean bean = employeeConverter.toBean(employeeDTO);
        bean.setOrganization(rootOrganization);
        bean.setTenant(rootOrganization.getTenant());
        // 设置项目管理员角色
        Role projectAdminRole = roleRepository.findByCode(Constant.PROJECT_ADMIN_ROLE_CODE)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001006001, Constant.PROJECT_ADMIN_ROLE_CODE));
        bean.setRoles(Lists.newArrayList(projectAdminRole));
        TenantEmployee tenantEmployee = employeeService.save(bean);
        if (log.isInfoEnabled()) {
            log.info("[{}] project admin instance {} was created.", clientIP, tenantEmployee.getName(), tenantEmployee.getId());
        }
        return ResultDTO.success();
    }

    /**
     * 重新分配项目管理员
     * @param employeeDTO 创建资源的DTO
     * @return 创建资源的DTO
     */
    @Timed
    @ApiOperation(value = "重新分配项目管理员")
    @PostMapping(value = "/projectAdmin/reassign/{id}")
    public ResultDTO<Void> reassignProjectAdmin(@Valid @RequestBody final EmployeeDTO employeeDTO, @PathVariable final UUID id, HttpServletRequest request) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001005001, String.valueOf(id)));
//        TenantEmployee tenantEmployee = this.tenantEmployeeRepository.findByMobileAndTenantId(user.getMobile(), employeeDTO.getTenantId());

        String clientIP = HttpUtils.getClientIP(request);
        // 获取项目信息
        UUID projectId = employeeDTO.getProjectId();
        if  (projectId == null) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001002002);
        }
        Project project = projectRepository.findById(projectId)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001002001, String.valueOf(projectId)));
        Organization rootOrganization = project.getRootOrganization();
        if (rootOrganization == null) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001002003);
        }
        //先查询OrganizationEmployee， OrganizationEmployeeRole
        OrganizationEmployee organizationEmployee = organizationEmployeeRepository.findByEmployeeMobileAndOrganizationId(
                user.getMobile(), employeeDTO.getOrganizationId());
        if (null == organizationEmployee) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001003001);
        }
        OrganizationEmployeeRole organizationEmployeeRole = organizationEmployeeRoleRepository.findByOrganizationEmployeeIdAndRoleCodeAndOrganizationId(
                organizationEmployee.getId(), Constant.PROJECT_ADMIN_ROLE_CODE, employeeDTO.getOrganizationId());
        if (null == organizationEmployeeRole) {
            throw ExceptionHolder.serviceException(UaaErrorCode.E2001006001);
        }
        //删除组织权限、组织关系
        this.organizationEmployeeRoleRepository.deleteById(organizationEmployeeRole.getId());
        this.organizationEmployeeRepository.deleteById(organizationEmployee.getId());
        // 创建管理员编码
        employeeDTO.setCode(Constant.projectAdminCode(project.getCode()));
        final EmployeeBean bean = employeeConverter.toBean(employeeDTO);
        bean.setOrganization(rootOrganization);
        // 设置项目管理员角色
        Role projectAdminRole = roleRepository.findByCode(Constant.PROJECT_ADMIN_ROLE_CODE)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001006001, Constant.PROJECT_ADMIN_ROLE_CODE));
        bean.setRoles(Lists.newArrayList(projectAdminRole));
        TenantEmployee tenantEmployee = employeeService.save(bean);
        if (log.isInfoEnabled()) {
            log.info("[{}] project admin instance {} was created.", clientIP, tenantEmployee.getName(), tenantEmployee.getId());
        }
        return ResultDTO.success();
    }

    /**
     * 删除操作
     * @param id 实体对象ID
     * @return 操作结果
     */
    @Timed
    @ApiOperation(value = "删除操作")
    @DeleteMapping(value = "/{id}")
    public ResultDTO<Void> delete(@PathVariable final UUID id, HttpServletRequest request) {
        String clientIP = HttpUtils.getClientIP(request);
        this.employeeService.delete(id);
        if (log.isInfoEnabled()) {
            log.info("[{}] employee instance {} was deleted.", clientIP, id);
        }
        return ResultDTO.success();
    }

    /**
     * 取得详细数据
     *
     * @param id 实体对象ID
     * @return 资源详细
     */
    @Timed
    @ApiOperation(value = "获取详细数据")
    @GetMapping(value = "/{id}")
    public ResultDTO<WebTenantEmployeeDTO> get(@PathVariable final UUID id) {
        final TenantEmployee model = this.tenantEmployeeRepository.findById(id)
                .orElseThrow(() -> ExceptionHolder.serviceException(UaaErrorCode.E2001001002, id.toString()));
        return this.tenantEmployeeConverter.toResultDTO(model);
    }
}
